package com.find.answer.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.find.answer.domain.common.BaseContextHolder;
import com.find.answer.domain.common.CustomException;
import com.find.answer.domain.dto.OrdersDto;
import com.find.answer.domain.dto.PageDto;
import com.find.answer.domain.po.*;
import com.find.answer.mapper.OrdersMapper;
import com.find.answer.service.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author Seon
 * @date 2022/11/5 11:31
 */
@Service
@Transactional
public class OrdersServiceImpl
        extends ServiceImpl<OrdersMapper, Orders> implements OrdersService {

    /*
订单的五种状态，分别是：1待付款，2待派送，3已派送，4已完成，5已取消
 */
    private static final Integer TO_BE_PAID = 1;
    private static final Integer TO_BE_DELIVERED = 2;
    private static final Integer DISPATCHED = 3;
    private static final Integer COMPLETED = 4;
    private static final Integer CANCELED = 5;

    @Autowired
    private ShoppingCartService shoppingCartService;

    @Autowired
    private OrdersDetailService ordersDetailService;

    @Autowired
    private UserService userService;


    @Autowired
    private AddressBookService addressBookService;
    @Override
    public void submitOrdersWithDish(OrdersDto ordersDto) {
        Long userId = BaseContextHolder.getCurrentId();
        User user = userService.getById(userId);

        LambdaQueryWrapper<ShoppingCart> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ShoppingCart::getUserId, userId);
        List<ShoppingCart> shoppingCarts = shoppingCartService.list(wrapper);
        if (shoppingCarts == null || shoppingCarts.size() == 0) {
            throw new CustomException("购物车为空，不能下单");
        }

        Long addressBookId = ordersDto.getAddressBookId();
        AddressBook addressBook = addressBookService.getById(addressBookId);
        if (addressBook == null) {
            throw new CustomException("用户地址信息有误，不能下单");
        }

        /*
        原子整数类，为了线程安全，使用AtomicInteger
         */
        AtomicInteger amount = new AtomicInteger(0);
        for (ShoppingCart goods : shoppingCarts) {
            int delta = goods.getAmount().multiply(new BigDecimal(goods.getNumber())).intValue();
            amount.addAndGet(delta);
        }
        /*
        下面的是单元素数组写法，学到了，新的方法。但是线程不安全。
        */
//        final BigDecimal[] sum = {BigDecimal.ZERO};
//        shoppingCarts.forEach(goods -> {
//            BigDecimal number = BigDecimal.valueOf(goods.getNumber());
//            BigDecimal amount = goods.getAmount();
//            BigDecimal result = amount.multiply(number);
//            sum[0] = sum[0].add(result);
//        });
        long id = IdWorker.getId();
        ordersDto.setUserName(user.getName());
        ordersDto.setNumber(String.valueOf(id));
        /*
        todo:为啥都是这里都是整数了，还是要用BigDecimal类呢？？？
         */
        ordersDto.setAmount(new BigDecimal(amount.get()));
        ordersDto.setUserId(userId);
        ordersDto.setStatus(TO_BE_DELIVERED);
        ordersDto.setOrderTime(LocalDateTime.now());
        ordersDto.setCheckoutTime(LocalDateTime.now());
        ordersDto.setConsignee(addressBook.getConsignee());
        ordersDto.setPhone(addressBook.getPhone());
        ordersDto.setAddress((addressBook.getProvinceName() == null ? "" : addressBook.getProvinceName())
                + (addressBook.getCityName() == null ? "" : addressBook.getCityName())
                + (addressBook.getDistrictName() == null ? "" : addressBook.getDistrictName())
                + (addressBook.getDetail() == null ? "" : addressBook.getDetail()));
        this.save(ordersDto);

        List<OrderDetail> collect = shoppingCarts.stream().map(items -> {
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(ordersDto.getId());
            BeanUtils.copyProperties(items, orderDetail);
            return orderDetail;
        }).collect(Collectors.toList());

        ordersDetailService.saveBatch(collect);
    }

    @Override
    public Page<OrdersDto> getOrdersPage(PageDto pageDto) {
        Page<Orders> ordersPage = new Page<>();
        Page<OrdersDto> ordersDtoPage = new Page<>();
        ordersPage.setSize(pageDto.getPageSize());
        ordersPage.setCurrent(pageDto.getPage());
        LambdaQueryWrapper<Orders> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Orders::getUserId, BaseContextHolder.getCurrentId());
        wrapper.orderByDesc(Orders::getOrderTime);
        this.page(ordersPage, wrapper);

        BeanUtils.copyProperties(ordersPage, ordersDtoPage, "records");

        List<Orders> records = ordersPage.getRecords();
        List<OrdersDto> collect = records.stream().map(items -> {
            OrdersDto ordersDto = new OrdersDto();
            BeanUtils.copyProperties(items, ordersDto);
            LambdaQueryWrapper<OrderDetail> detailWrapper = new LambdaQueryWrapper<>();
            detailWrapper.eq(OrderDetail::getOrderId, items.getId());
            List<OrderDetail> list = ordersDetailService.list(detailWrapper);
            ordersDto.setOrderDetails(list);
            return ordersDto;
        }).collect(Collectors.toList());
        ordersDtoPage.setRecords(collect);
        return ordersDtoPage;
    }

    @Override
    public void deleteShoppingCart() {
        LambdaQueryWrapper<ShoppingCart> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ShoppingCart::getUserId, BaseContextHolder.getCurrentId());
        shoppingCartService.remove(wrapper);
    }

    @Override
    public Page<OrdersDto> getPageCondition(PageDto pageDto, String beginTime, String endTime, String number) {
        // todo: 分页查询搞一下。
        return null;
    }
}
